package orbit

import (
	"gddgame.cc/galaxy/binocle"
	"gddgame.cc/galaxy/common/bootstrap"
	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/common/feature/orbit"
	"gddgame.cc/galaxy/core/routers"
	"gddgame.cc/galaxy/project/orbit/orbit/common"
	"gddgame.cc/galaxy/server/composer"

	"gddgame.cc/galaxy/satellite/formula/comet"
	"gddgame.cc/galaxy/server/web"
)

const (
	_ comet.DN = iota
	CHAT
	SYNC
	CHESS
)

const (
	Version = "1.0.0"
)

type Config struct {
	Node    string        `json:"node"`
	Tcp     string        `json:"tcp"`
	Server  string        `json:"server"`
	Udp     string        `json:"udp" galaxy:"option"`
	Web     string        `json:"web" galaxy:"option"`
	Options comet.Options `json:"options" galaxy:"option"`
}

type Component struct {
	Config *Config

	composer.Composer `inject:""`

	Web     web.Engine      `inject:""`
	Boot    *bootstrap.Boot `inject:""`
	Binocle binocle.Agent   `inject:""`

	Comet *comet.Server `galaxy:"inject"`
}

func (c *Component) Init(register composer.Register, builder composer.Builder) error {
	var err error
	// 注册为服务
	agent, err := c.Binocle.Service(binocle.Config{
		Name:    "orbit",
		Node:    c.Config.Node,
		Version: Version,
		Meta: map[string]string{
			binocle.ServerMeta: c.Config.Server,
		},
	})
	if err != nil {
		return err
	}
	if err := AuthHandler(builder, agent); err != nil {
		return err
	}
	if err := builder.BindInstance("agent", agent); err != nil {
		return err
	}

	s, err := comet.NewServer(builder, c.Config.Tcp, c.Config.Udp, c.Config.Options)
	if err != nil {
		return err
	}
	s.SetLogger(builder)
	s.SetDebug(builder.IsDebug())

	Env := orbit.NewEnvironment(builder, agent, builder.Cache(agent.FullName()))

	register.Attach(c.Web.Register(c.Config.Web, func(r web.Router, handler web.RouterHandler) error {
		// 挂载websocket
		if err := s.Attach(r); err != nil {
			return err
		}

		// app接口
		authMiddle := MultiAuthMiddle(nil, routers.AppAuth)

		syncRouter := handler("/sync")
		web.Restful(syncRouter)
		syncRouter.Use(authMiddle)
		SyncAppHandler(builder, syncRouter, c.Config)

		chatRouter := handler("/chat")
		web.Restful(chatRouter)
		chatRouter.Use(authMiddle)
		ChatAppHandler(builder, chatRouter, c.Config)

		taskRouter := handler("/chess")
		web.Restful(taskRouter)
		taskRouter.Use(authMiddle)
		ChessAppHandler(builder, taskRouter, c.Config)

		// 管理接口
		orbitRouter := handler("/orbit")
		web.Restful(orbitRouter)
		routers.ManageAuth(builder, orbitRouter)
		SyncManageHandler(builder, orbitRouter.Group("/sync"), c.Config)
		ChatManageHandler(builder, orbitRouter.Group("/chat"), c.Config)
		ChessManageHandler(builder, orbitRouter.Group("/chess"), c.Config)
		return nil
	}))

	// 设定授权接口
	s.Auth(authHandle)
	register.Attach(s.Register(func(handler comet.InterfaceHandler) error {
		controlService := &common.ControlService{
			Logger:  builder,
			Service: agent,
		}
		agent.Cluster().RegisterBalance(controlService)
		handler(CHAT, ChatHandler(builder, c.Config, Env))
		handler(SYNC, SyncHandler(builder, c.Config, Env))
		handler(CHESS, ChessHandler(builder, c.Config, Env, controlService))
		return nil
	}))
	register.AttachListener(s)

	c.Comet = s

	// 设定监控项
	agent.AddMetrics().Exec("online", func(key string) float32 {
		return float32(s.ClientNum())
	})

	return nil
}
